home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / graphic / jpegsrc4.zip / JMEMDOS.C < prev    next >
C/C++ Source or Header  |  1992-07-26  |  18KB  |  614 lines

  1. /*
  2.  * jmemdos.c  (jmemsys.c)
  3.  *
  4.  * Copyright (C) 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file provides an MS-DOS-compatible implementation of the system-
  9.  * dependent portion of the JPEG memory manager.  Temporary data can be
  10.  * stored in extended or expanded memory as well as in regular DOS files.
  11.  *
  12.  * If you use this file, you must be sure that NEED_FAR_POINTERS is defined
  13.  * if you compile in a small-data memory model; it should NOT be defined if
  14.  * you use a large-data memory model.  This file is not recommended if you
  15.  * are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
  16.  *
  17.  * Based on code contributed by Ge' Weijers.
  18.  */
  19.  
  20. /*
  21.  * If you have both extended and expanded memory, you may want to change the
  22.  * order in which they are tried in jopen_backing_store.  On a 286 machine
  23.  * expanded memory is usually faster, since extended memory access involves
  24.  * an expensive protected-mode-and-back switch.  On 386 and better, extended
  25.  * memory is usually faster.  As distributed, the code tries extended memory
  26.  * first (what? not everyone has a 386? :-).
  27.  *
  28.  * You can disable use of extended/expanded memory entirely by altering these
  29.  * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
  30.  */
  31.  
  32. #ifndef XMS_SUPPORTED
  33. #define XMS_SUPPORTED  1
  34. #endif
  35. #ifndef EMS_SUPPORTED
  36. #define EMS_SUPPORTED  1
  37. #endif
  38.  
  39.  
  40. #include "jinclude.h"
  41. #include "jmemsys.h"
  42.  
  43. #ifdef INCLUDES_ARE_ANSI
  44. #include <stdlib.h>        /* to declare malloc(), free(), getenv() */
  45. #else
  46. extern void * malloc PP((size_t size));
  47. extern void free PP((void *ptr));
  48. extern char * getenv PP((const char * name));
  49. #endif
  50.  
  51. #ifdef NEED_FAR_POINTERS
  52.  
  53. #ifdef __TURBOC__
  54. /* These definitions work for Borland C (Turbo C) */
  55. #include <alloc.h>        /* need farmalloc(), farfree() */
  56. #define far_malloc(x)    farmalloc(x)
  57. #define far_free(x)    farfree(x)
  58. #else
  59. /* These definitions work for Microsoft C and compatible compilers */
  60. #include <malloc.h>        /* need _fmalloc(), _ffree() */
  61. #define far_malloc(x)    _fmalloc(x)
  62. #define far_free(x)    _ffree(x)
  63. #endif
  64.  
  65. #endif
  66.  
  67. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  68. #define READ_BINARY    "r"
  69. #else
  70. #define READ_BINARY    "rb"
  71. #endif
  72.  
  73.  
  74. /*
  75.  * Declarations for assembly-language support routines (see jmemdosa.asm).
  76.  *
  77.  * The functions are declared "far" as are all pointer arguments;
  78.  * this ensures the assembly source code will work regardless of the
  79.  * compiler memory model.  We assume "short" is 16 bits, "long" is 32.
  80.  */
  81.  
  82. typedef void far * XMSDRIVER;    /* actually a pointer to code */
  83. typedef struct {        /* registers for calling XMS driver */
  84.     unsigned short ax, dx, bx;
  85.     void far * ds_si;
  86.       } XMScontext;
  87. typedef struct {        /* registers for calling EMS driver */
  88.     unsigned short ax, dx, bx;
  89.     void far * ds_si;
  90.       } EMScontext;
  91.  
  92. EXTERN short far jdos_open PP((short far * handle, char far * filename));
  93. EXTERN short far jdos_close PP((short handle));
  94. EXTERN short far jdos_seek PP((short handle, long offset));
  95. EXTERN short far jdos_read PP((short handle, void far * buffer,
  96.                    unsigned short count));
  97. EXTERN short far jdos_write PP((short handle, void far * buffer,
  98.                 unsigned short count));
  99. EXTERN void far jxms_getdriver PP((XMSDRIVER far *));
  100. EXTERN void far jxms_calldriver PP((XMSDRIVER, XMScontext far *));
  101. EXTERN short far jems_available PP((void));
  102. EXTERN void far jems_calldriver PP((EMScontext far *));
  103.  
  104.  
  105. static external_methods_ptr methods; /* saved for access to error_exit */
  106.  
  107. static long total_used;        /* total FAR memory requested so far */
  108.  
  109.  
  110. /*
  111.  * Selection of a file name for a temporary file.
  112.  * This is highly system-dependent, and you may want to customize it.
  113.  */
  114.  
  115. static int next_file_num;    /* to distinguish among several temp files */
  116.  
  117. LOCAL void
  118. select_file_name (char * fname)
  119. {
  120.   const char * env;
  121.   char * ptr;
  122.   FILE * tfile;
  123.  
  124.   /* Keep generating file names till we find one that's not in use */
  125.   for (;;) {
  126.     /* Get temp directory name from environment TMP or TEMP variable;
  127.      * if none, use "."
  128.      */
  129.     if ((env = (const char *) getenv("TMP")) == NULL)
  130.       if ((env = (const char *) getenv("TEMP")) == NULL)
  131.     env = ".";
  132.     if (*env == '\0')        /* null string means "." */
  133.       env = ".";
  134.     ptr = fname;        /* copy name to fname */
  135.     while (*env != '\0')
  136.       *ptr++ = *env++;
  137.     if (ptr[-1] != '\\' && ptr[-1] != '/')
  138.       *ptr++ = '\\';        /* append backslash if not in env variable */
  139.     /* Append a suitable file name */
  140.     next_file_num++;        /* advance counter */
  141.     sprintf(ptr, "JPG%03d.TMP", next_file_num);
  142.     /* Probe to see if file name is already in use */
  143.     if ((tfile = fopen(fname, READ_BINARY)) == NULL)
  144.       break;
  145.     fclose(tfile);        /* oops, it's there; close tfile & try again */
  146.   }
  147. }
  148.  
  149.  
  150. /*
  151.  * Near-memory allocation and freeing are controlled by the regular library
  152.  * routines malloc() and free().
  153.  */
  154.  
  155. GLOBAL void *
  156. jget_small (size_t sizeofobject)
  157. {
  158.   /* near data space is NOT counted in total_used */
  159. #ifndef NEED_FAR_POINTERS
  160.   total_used += sizeofobject;
  161. #endif
  162.   return (void *) malloc(sizeofobject);
  163. }
  164.  
  165. GLOBAL void
  166. jfree_small (void * object)
  167. {
  168.   free(object);
  169. }
  170.  
  171.  
  172. /*
  173.  * Far-memory allocation and freeing
  174.  */
  175.  
  176. #ifdef NEED_FAR_POINTERS
  177.  
  178. GLOBAL void FAR *
  179. jget_large (size_t sizeofobject)
  180. {
  181.   total_used += sizeofobject;
  182.   return (void FAR *) far_malloc(sizeofobject);
  183. }
  184.  
  185. GLOBAL void
  186. jfree_large (void FAR * object)
  187. {
  188.   far_free(object);
  189. }
  190.  
  191. #endif
  192.  
  193.  
  194. /*
  195.  * This routine computes the total memory space available for allocation.
  196.  * It's impossible to do this in a portable way; our current solution is
  197.  * to make the user tell us (with a default value set at compile time).
  198.  * If you can actually get the available space, it's a good idea to subtract
  199.  * a slop factor of 5% or so.
  200.  */
  201.  
  202. #ifndef DEFAULT_MAX_MEM        /* so can override from makefile */
  203. #define DEFAULT_MAX_MEM        300000L /* for total usage about 450K */
  204. #endif
  205.  
  206. GLOBAL long
  207. jmem_available (long min_bytes_needed, long max_bytes_needed)
  208. {
  209.   return methods->max_memory_to_use - total_used;
  210. }
  211.  
  212.  
  213. /*
  214.  * Backing store (temporary file) management.
  215.  * Backing store objects are only used when the value returned by
  216.  * jmem_available is less than the total space needed.  You can dispense
  217.  * with these routines if you have plenty of virtual memory; see jmemnobs.c.
  218.  */
  219.  
  220. /*
  221.  * For MS-DOS we support three types of backing storage:
  222.  *   1. Conventional DOS files.  We access these by direct DOS calls rather
  223.  *      than via the stdio package.  This provides a bit better performance,
  224.  *      but the real reason is that the buffers to be read or written are FAR.
  225.  *      The stdio library for small-data memory models can't cope with that.
  226.  *   2. Extended memory, accessed per the XMS V2.0 specification.
  227.  *   3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
  228.  * You'll need copies of those specs to make sense of the related code.
  229.  * The specs are available by Internet FTP from SIMTEL20 and its various
  230.  * mirror sites; see microsoft/xms20.arc and info/limems41.zip.
  231.  */
  232.  
  233.  
  234. /*
  235.  * Access methods for a DOS file.
  236.  */
  237.  
  238.  
  239. METHODDEF void
  240. read_file_store (backing_store_ptr info, void FAR * buffer_address,
  241.          long file_offset, long byte_count)
  242. {
  243.   if (jdos_seek(info->handle.file_handle, file_offset))
  244.     ERREXIT(methods, "seek failed on temporary file");
  245.   /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
  246.   if (byte_count > 65535L)    /* safety check */
  247.     ERREXIT(methods, "MAX_ALLOC_CHUNK should be less than 64K");
  248.   if (jdos_read(info->handle.file_handle, buffer_address,
  249.         (unsigned short) byte_count))
  250.     ERREXIT(methods, "read failed on temporary file");
  251. }
  252.  
  253.  
  254. METHODDEF void
  255. write_file_store (backing_store_ptr info, void FAR * buffer_address,
  256.           long file_offset, long byte_count)
  257. {
  258.   if (jdos_seek(info->handle.file_handle, file_offset))
  259.     ERREXIT(methods, "see